package rayTracer;

import java.util.ArrayList;

import javax.vecmath.Point3d;
import primitive3D.Primitive3D;
import static rayTracer.ApplicationInterface.*;


public class Scene {
	public ArrayList<Primitive3D> figures;
	Octree octree;
	double minX;
	double minY;
	double minZ;	
	double maxX;
	double maxY;
	double maxZ;
	
	public Scene(){
		figures = new ArrayList<Primitive3D>();
		octree = null;
		minX = Double.POSITIVE_INFINITY;
		minY = Double.POSITIVE_INFINITY;
		minZ = Double.POSITIVE_INFINITY;
		
		maxX = Double.NEGATIVE_INFINITY;
		maxY = Double.NEGATIVE_INFINITY;
		maxZ = Double.NEGATIVE_INFINITY;
	}
	
	public Scene( ArrayList<Primitive3D> figures ){		
		//sceneFigures = figures;
		for( Primitive3D p : figures )
			figures.add(p);
	}
	
	public void add( Primitive3D figure){
		figures.add(figure);	
			
		if( figure.components != null ){
			for( Primitive3D p : figure.components ){
				if( p.bb.min.x < minX )
					minX = p.bb.min.x;
				if( p.bb.min.y < minY )
					minY = p.bb.min.y;
				if( p.bb.min.z < minZ )
					minZ = p.bb.min.z;
				if( p.bb.max.x > maxX )
					maxX = p.bb.max.x;
				if( p.bb.max.y > maxY )
					maxY = p.bb.max.y;
				if( p.bb.max.z > maxZ )
					maxZ = p.bb.max.z;
			}
		}else{
			if( figure.bb.min.x < minX )
				minX = figure.bb.min.x;
			if( figure.bb.min.y < minY )
				minY = figure.bb.min.y;
			if( figure.bb.min.z < minZ )
				minZ = figure.bb.min.z;
			if( figure.bb.max.x > maxX )
				maxX = figure.bb.max.x;
			if( figure.bb.max.y > maxY )
				maxY = figure.bb.max.y;
			if( figure.bb.max.z > maxZ )
				maxZ = figure.bb.max.z;
		}
		
	}
	public void prepareScene(){
		Double[] dims = new Double[]{maxX, maxY, maxZ, minX, minY, minZ};
		double maxSceneDimension = Double.NEGATIVE_INFINITY;
		for( double d : dims ){
			if( Math.abs(d) > maxSceneDimension )
				maxSceneDimension = Math.abs(d);
		}
		
		octree = new Octree( new Point3d(OCTREE_POSITION), maxSceneDimension,
				OCTREE_MAX_PRIMITIVES_PER_NODE );
		/*
		for( Primitive3D p : sceneFigures ){
			addFigureToOctree(p);
		}
		*/
		int i,j;
		
		for( i=0; i< figures.size() ; i++ ){
			j=-1;
			if( figures.get(i).components != null ){
				ArrayList<Primitive3D> pList = figures.get(i).components;
				
				for( j=0 ; j<pList.size() ; j++ ){
					pList.get(j).name = String.valueOf(j);
					//pList.get(j).shader = figures.get(i).shader;
					octree.insertObject(pList.get(j));
					//System.out.println("i="+i+"  j="+j);
				}
				
			}else{
				octree.insertObject(figures.get(i));
				//System.out.println("i="+i+"  j="+j);
			}
			
		}
		//System.out.println(octree);	
	}
	
	public int intersectsRay( Ray ray, ArrayList<Double> distances, ArrayList<Primitive3D> figures ) throws Exception{
		//prepareScene();
		/*
		for( Primitive3D p : sceneFigures ){
			addFigureToOctree(p);
		}	
		*/
		return octree.intersectsRay(ray, distances, figures);
	}
	
	public ArrayList<Primitive3D> getFigures(){
		return figures;
	}

	public String toString(){
		StringBuffer str = new StringBuffer();
		str.append("SCENE CONTENTS , cantidad de figuras = " + figures.size());
		for( int i=0 ; i<figures.size(); i++){			
			str.append("\n====> FIGURE " + i + "\n");
			str.append(figures.get(i));
		}
		return str.toString();
	}
	
	@SuppressWarnings("unused")
	private void addFigureToOctree(Primitive3D figure) {
		if( figure.components != null ){
			for( Primitive3D p : figure.components ){
				octree.insertObject(p);
			}
		}else{
			octree.insertObject(figure);
		}
	}
	
}
